/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package kebut.logic;

import java.util.Random;

public class stegano extends CryptoBase {
    public byte[] plainByte;
    public byte[] sourceByte;
    public byte[] embedByte;
    public byte[] extractByte;
    public String extension;
    public Random rand;
    public long seed;
    public int status;
    public boolean isError = false;
    public int maxEmbed = 0; // dalam satuan byte
    
    //constructor for embed
    public stegano(byte[] plain, byte[] source, String extension, String key, int status) {
        this.plainByte = plain;
        this.sourceByte = source;
        this.extension = extension;
        this.embedByte = new byte[source.length];
        this.seed = countRandomSeed(key);
        this.status = status;
        maxEmbed = totalSizePlainText();
    }
    
    //constructor for extract
    public stegano(byte[] embed, String key, int status) {
        this.embedByte = embed;
        this.seed = countRandomSeed(key);
        this.status = status;
    }
    
    public int totalSizePlainText() {
        int x = (sourceByte.length - 58) / (40/status);
        String s = ""+x;
        int count = x - s.length() - 6;
        return count;
    }
    
    public long countRandomSeed(String text) {
        long sum = 0;
        for (int i = 0; i < text.length(); i++) {
            sum+=(i+1)*text.charAt(i);
        }
        return sum;
    }
    
    @Override
    public void encrypt() {
        rand = new Random(seed);
        //duplicate source for counting psnr
        System.arraycopy(sourceByte, 0, embedByte, 0, sourceByte.length);

        int count = totalSizePlainText();
        
        maxEmbed = count;

        String s = ""+plainByte.length+";"+extension+";";
        byte length[] = s.getBytes();
        
        int len = 0;
        
        if (status == 3) {
            if (((int)plainByte.length+length.length+1) % 3 != 0) {
                len = ((int)plainByte.length+length.length+1) + (3 - (((int)plainByte.length+length.length+1) % 3));
            } else {
                len = (int)plainByte.length+length.length+1;
            }
        } else {
            len = (int)plainByte.length+length.length+1;
        }

        byte[] b4 = new byte[len];
        System.arraycopy(plainByte, 0, b4, 0, plainByte.length);

        for (int i = (int)plainByte.length-1; i >= 0; i--) {
            b4[i+length.length] = b4[i];
        }
        System.arraycopy(length, 0, b4, 0, length.length);
        
        b4[(int)plainByte.length+length.length] = 0x00;
        
        if (status == 3) {
            for (int i = (int)plainByte.length+length.length+1; i < b4.length; i++) {
                b4[i] = 0x00;
            }
        }
        
        System.out.println(maxEmbed + "|" + b4.length);

        int x = 58;
        if (b4.length <= count) {
            if (status == 1) {
                for (int i = 0; i < (b4.length*8)-1; i++) {
                    //System.out.print(getBit(b4,i));
                    if (getBit(b4, i) == 1) {
                        embedByte[x] = (byte) (embedByte[x] | 0x01);
                    } else {
                        embedByte[x] = (byte) (embedByte[x] & ~(0x01));
                    }
                    //System.out.print( x + "|");
                    x+=rand.nextInt(5) + 1;
                    if (x>=embedByte.length) {
                        x = 58 + rand.nextInt(5) + 1;
                    }
                }
            } else if (status == 2) {
                for (int i = 0; i < (b4.length*8)-1; i+=2) {
                    //System.out.print(getBit(b4,i));
                    if (getBit(b4, i) == 1) {
                        embedByte[x] = (byte) (embedByte[x] | 0x02);
                    } else {
                        embedByte[x] = (byte) (embedByte[x] & ~(0x02));
                    }
                    if (getBit(b4, i+1) == 1) {
                        embedByte[x] = (byte) (embedByte[x] | 0x01);
                    } else {
                        embedByte[x] = (byte) (embedByte[x] & ~(0x01));
                    }
                    //System.out.print( x + "|");
                    x+=rand.nextInt(5) + 1;
                    if (x>=embedByte.length) {
                        x = 58 + rand.nextInt(5) + 1;
                    }
                }
            } else if (status == 3) {
                for (int i = 0; i < (b4.length*8)-1; i+=3) {
                    //System.out.print(getBit(b4,i));
                    if (getBit(b4, i) == 1) {
                        embedByte[x] = (byte) (embedByte[x] | 0x04);
                    } else {
                        embedByte[x] = (byte) (embedByte[x] & ~(0x04));
                    }
                    if (getBit(b4, i+1) == 1) {
                        embedByte[x] = (byte) (embedByte[x] | 0x02);
                    } else {
                        embedByte[x] = (byte) (embedByte[x] & ~(0x02));
                    }
                    if (getBit(b4, i+2) == 1) {
                        embedByte[x] = (byte) (embedByte[x] | 0x01);
                    } else {
                        embedByte[x] = (byte) (embedByte[x] & ~(0x01));
                    }
                    //System.out.print( x + "|");
                    x+=rand.nextInt(5) + 1;
                    if (x>=embedByte.length) {
                        x = 58 + rand.nextInt(5) + 1;
                    }
                }
            }
        } else {
            isError = true;
        }           
    }

    @Override
    public void decrypt() {
        rand = new Random(seed);
        //get length of plain text
        if (status == 1) {
            byte[] extract = new byte[(int)embedByte.length];
            int x = 58;
            int i = 0;
            boolean isLength = false;
            while (!isLength && (x < (int)embedByte.length)) { 
                setBit(extract,i,getBit(embedByte,x*8+7));
                if ((i+1) % 8 == 0) {
                    if (extract[i/8] == (byte)';') {
                        isLength = true;
                    } else {
                        i++;
                        x+=rand.nextInt(5) + 1;
                    }
                } else {
                    i++;
                    x+=rand.nextInt(5) + 1;
                }
            }
            
            if (x < (int)embedByte.length) {
                int length = 0;
                int j = 0;
                int c = 0;

                while (extract[j] != (byte)';') {
                    if (extract[j] < 0){
                        c = 256 + (int)extract[j];
                    } else {
                        c = (int)extract[j];
                    }
                    length = length * 10 + (c-48);
                    j++;
                }
                
                

                if (length < 0) {
                    isError = true;
                    extractByte = new byte[100];
                    
                    byte[] extract3 = new byte[100];
                    i = 0;
                    x+=rand.nextInt(5) + 1;
                    isLength = false;
                    while (!isLength && x < (int)embedByte.length) { 
                        setBit(extract3,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if ((i/8) == (extract3.length-1)) {
                                isLength = true;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    
                } else if (length > 1000000000) {
                    isError = true;
                    extractByte = new byte[100];
                    
                    byte[] extract3 = new byte[100];
                    i = 0;
                    x+=rand.nextInt(5) + 1;
                    isLength = false;
                    while (!isLength && x < (int)embedByte.length) { 
                        setBit(extract3,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if ((i/8) == (extract3.length-1)) {
                                isLength = true;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                
                }else {

                    extractByte = new byte[length];

                    //get extension of plain text
                    byte[] extract2 = new byte[(int)embedByte.length];
                    i = 0;
                    x+=rand.nextInt(5) + 1;
                    isLength = false;
                    while (!isLength && x < (int)embedByte.length) { 
                        setBit(extract2,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if (extract2[i/8] == (byte)';') {
                                isLength = true;
                            } else {

                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    
                    if (x < (int)embedByte.length) {

                        String ext = "";
                        j = 0;

                        while (extract2[j] != (byte)';') {
                            ext += (char)extract2[j];
                            j++;
                        }

                        extension = ext;
                        //get plain text
                        byte[] extract3 = new byte[length+1];
                        i = 0;
                        x+=rand.nextInt(5) + 1;
                        isLength = false;
                        while (!isLength && x < (int)embedByte.length) { 
                            setBit(extract3,i,getBit(embedByte,x*8+7));
                            if ((i+1) % 8 == 0) {
                                if ((i/8) == (extract3.length-1)) {
                                    isLength = true;
                                } else {
                                    i++;
                                    x+=rand.nextInt(5) + 1;
                                }
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        }
                        System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    } else {
                        isError = true;
                        extractByte = new byte[100];
                        
                        byte[] extract3 = new byte[100];
                        i = 0;
                        x+=rand.nextInt(5) + 1;
                        isLength = false;
                        while (!isLength && x < (int)embedByte.length) { 
                            setBit(extract3,i,getBit(embedByte,x*8+7));
                            if ((i+1) % 8 == 0) {
                                if ((i/8) == (extract3.length-1)) {
                                    isLength = true;
                                } else {
                                    i++;
                                    x+=rand.nextInt(5) + 1;
                                }
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        }
                        System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    }
                }
            } else {
                isError = true;
                extractByte = new byte[100];
                
                byte[] extract3 = new byte[100];
                i = 0;
                x+=rand.nextInt(5) + 1;
                isLength = false;
                while (!isLength && x < (int)embedByte.length) { 
                    setBit(extract3,i,getBit(embedByte,x*8+7));
                    if ((i+1) % 8 == 0) {
                        if ((i/8) == (extract3.length-1)) {
                            isLength = true;
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    } else {
                        i++;
                        x+=rand.nextInt(5) + 1;
                    }
                }
                System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
            }
        } else if (status == 2) {
            byte[] extract = new byte[(int)embedByte.length];
            int x = 58;
            int i = 0;
            boolean isLength = false;
            while (!isLength && x < (int)embedByte.length) { 
                setBit(extract,i,getBit(embedByte,x*8+6));i++;
                setBit(extract,i,getBit(embedByte,x*8+7));
                if ((i+1) % 8 == 0) {
                    if (extract[i/8] == (byte)';') {
                        isLength = true;
                    } else {
                        i++;
                        x+=rand.nextInt(5) + 1;
                    }
                } else {
                    i++;
                    x+=rand.nextInt(5) + 1;
                }
            }

            if (x < (int)embedByte.length) {
                int length = 0;
                int j = 0;

                while (extract[j] != (byte)';') {
                    length = length * 10 + (extract[j]-48);
                    j++;
                }
                
                if (length < 0) {
                    isError = true;
                    extractByte = new byte[100];
                    
                    byte[] extract3 = new byte[100];
                    i = 0;
                    x+=rand.nextInt(5) + 1;
                    isLength = false;
                    while (!isLength && x < (int)embedByte.length) { 
                        setBit(extract3,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if ((i/8) == (extract3.length-1)) {
                                isLength = true;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    
                } else if (length > 1000000000) {
                    isError = true;
                    extractByte = new byte[100];
                    
                    byte[] extract3 = new byte[100];
                    i = 0;
                    x+=rand.nextInt(5) + 1;
                    isLength = false;
                    while (!isLength && x < (int)embedByte.length) { 
                        setBit(extract3,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if ((i/8) == (extract3.length-1)) {
                                isLength = true;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                
                }else {

                    extractByte = new byte[length];

                    //get extension of plain text
                    byte[] extract2 = new byte[(int)embedByte.length];
                    i = 0;
                    x+=rand.nextInt(5) + 1;
                    isLength = false;
                    while (!isLength && x < (int)embedByte.length) { 
                        setBit(extract2,i,getBit(embedByte,x*8+6));i++;
                        setBit(extract2,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if (extract2[i/8] == (byte)';') {
                                isLength = true;
                            } else {

                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    
                    if (x < (int)embedByte.length) {

                        String ext = "";
                        j = 0;

                        while (extract2[j] != (byte)';') {
                            ext += (char)extract2[j];
                            j++;
                        }

                        extension = ext;


                        //get plain text
                        byte[] extract3 = new byte[length+1];
                        i = 0;
                        x+=rand.nextInt(5) + 1;
                        isLength = false;
                        while (!isLength) { 
                            setBit(extract3,i,getBit(embedByte,x*8+6));i++;
                            setBit(extract3,i,getBit(embedByte,x*8+7));
                            if ((i+1) % 8 == 0) {
                                if ((i/8) == (extract3.length-1)) {
                                    isLength = true;
                                } else {
                                    i++;
                                    x+=rand.nextInt(5) + 1;
                                }
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        }
                        System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    } else {
                        isError = true;
                        extractByte = new byte[100];
                        
                        byte[] extract3 = new byte[100];
                        i = 0;
                        x+=rand.nextInt(5) + 1;
                        isLength = false;
                        while (!isLength && x < (int)embedByte.length) { 
                            setBit(extract3,i,getBit(embedByte,x*8+7));
                            if ((i+1) % 8 == 0) {
                                if ((i/8) == (extract3.length-1)) {
                                    isLength = true;
                                } else {
                                    i++;
                                    x+=rand.nextInt(5) + 1;
                                }
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        }
                        System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    }
                }
            } else {
                isError = true;
                extractByte = new byte[100];
                
                byte[] extract3 = new byte[100];
                i = 0;
                x+=rand.nextInt(5) + 1;
                isLength = false;
                while (!isLength && x < (int)embedByte.length) { 
                    setBit(extract3,i,getBit(embedByte,x*8+7));
                    if ((i+1) % 8 == 0) {
                        if ((i/8) == (extract3.length-1)) {
                            isLength = true;
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    } else {
                        i++;
                        x+=rand.nextInt(5) + 1;
                    }
                }
                System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
            }
        } else if (status == 3) {
            byte[] extract = new byte[(int)embedByte.length];
            int x = 58;
            int i = 0;
            int stat = 0;
            boolean isLength = false;
            while (!isLength && x < embedByte.length) { 
                setBit(extract,i,getBit(embedByte,x*8+5));
                if ((i+1) % 8 == 0) {
                    if (extract[i/8] == (byte)';') {
                        isLength = true;
                        stat = 1;
                        break;
                    } else {
                        i++;
                    }
                } else {
                    i++;
                }
                setBit(extract,i,getBit(embedByte,x*8+6));
                if ((i+1) % 8 == 0) {
                    if (extract[i/8] == (byte)';') {
                        isLength = true;
                        stat = 2;
                        break;
                    } else {
                        i++;
                    }
                } else {
                    i++;
                }
                setBit(extract,i,getBit(embedByte,x*8+7));
                if ((i+1) % 8 == 0) {
                    if (extract[i/8] == (byte)';') {
                        isLength = true;
                        stat = 3;
                        break;
                    } else {
                        i++;
                        x+=rand.nextInt(5) + 1;
                    }
                } else {
                    i++;
                    x+=rand.nextInt(5) + 1;
                }
            }
            
            if (x < (int)embedByte.length) {

                int length = 0;
                int j = 0;

                while (extract[j] != (byte)';') {
                    length = length * 10 + (extract[j]-48);
                    j++;
                }
                
                if (length < 0) {
                    isError = true;
                    extractByte = new byte[100];
                    
                    byte[] extract3 = new byte[100];
                    i = 0;
                    x+=rand.nextInt(5) + 1;
                    isLength = false;
                    while (!isLength && x < (int)embedByte.length) { 
                        setBit(extract3,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if ((i/8) == (extract3.length-1)) {
                                isLength = true;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    
                } else if (length > 1000000000) {
                    isError = true;
                    extractByte = new byte[100];
                    
                    byte[] extract3 = new byte[100];
                    i = 0;
                    x+=rand.nextInt(5) + 1;
                    isLength = false;
                    while (!isLength && x < (int)embedByte.length) { 
                        setBit(extract3,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if ((i/8) == (extract3.length-1)) {
                                isLength = true;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                
                }else {

                    extractByte = new byte[length];

                    //get extension of plain text
                    byte[] extract2 = new byte[(int)embedByte.length];
                    i = 0;
                    isLength = false;
                    if (stat == 1) {
                        setBit(extract2,i,getBit(embedByte,x*8+6));
                        if ((i+1) % 8 == 0) {
                            if (extract2[i/8] == (byte)';') {
                                isLength = true;
                                stat = 2;
                            } else {
                                i++;
                            }
                        } else {
                            i++;
                        }
                        setBit(extract2,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if (extract2[i/8] == (byte)';') {
                                isLength = true;
                                stat = 3;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    } else if (stat == 2) {
                        setBit(extract2,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if (extract2[i/8] == (byte)';') {
                                isLength = true;
                                stat = 3;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    } else if (stat == 3) {
                        x+=rand.nextInt(5) + 1;
                    }
                    while (!isLength && x < embedByte.length) { 
                        setBit(extract2,i,getBit(embedByte,x*8+5));
                        if ((i+1) % 8 == 0) {
                            if (extract2[i/8] == (byte)';') {
                                isLength = true;
                                stat = 1;
                                break;
                            } else {
                                i++;
                            }
                        } else {
                            i++;
                        }
                        setBit(extract2,i,getBit(embedByte,x*8+6));
                        if ((i+1) % 8 == 0) {
                            if (extract2[i/8] == (byte)';') {
                                isLength = true;
                                stat = 2;
                                break;
                            } else {
                                i++;
                            }
                        } else {
                            i++;
                        }
                        setBit(extract2,i,getBit(embedByte,x*8+7));
                        if ((i+1) % 8 == 0) {
                            if (extract2[i/8] == (byte)';') {
                                isLength = true;
                                stat = 3;
                                break;
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    }
                    
                    if (x < (int)embedByte.length) {

                        String ext = "";
                        j = 0;

                        while (extract2[j] != (byte)';') {
                            ext += (char)extract2[j];
                            j++;
                        }

                        extension = ext;

                        int count = String.valueOf(length).length() + 1 + extension.length() + 1 + length+ 1;
                        if (count % 3 != 0) {
                            count += (3 - count % 3);
                        }
                        //System.out.println(count);
                        //get plain text
                        byte[] extract3 = new byte[count];
                        i = 0;
                        isLength = false;
                        if (stat == 1) {
                            setBit(extract3,i,getBit(embedByte,x*8+6));
                            if ((i+1) % 8 == 0) {
                                if (extract3[i/8] == (byte)';') {
                                    isLength = true;
                                    stat = 2;
                                } else {
                                    i++;
                                }
                            } else {
                                i++;
                            }
                            setBit(extract3,i,getBit(embedByte,x*8+7));
                            if ((i+1) % 8 == 0) {
                                if (extract3[i/8] == (byte)';') {
                                    isLength = true;
                                    stat = 3;
                                } else {
                                    i++;
                                    x+=rand.nextInt(5) + 1;
                                }
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else if (stat == 2) {
                            setBit(extract3,i,getBit(embedByte,x*8+7));
                            if ((i+1) % 8 == 0) {
                                if (extract3[i/8] == (byte)';') {
                                    isLength = true;
                                    stat = 3;
                                } else {
                                    i++;
                                    x+=rand.nextInt(5) + 1;
                                }
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        } else if (stat == 3) {
                            x+=rand.nextInt(5) + 1;
                        }
                        while (!isLength) { 
                            setBit(extract3,i,getBit(embedByte,x*8+5));
                            if ((i+1) % 8 == 0) {
                                if ((i/8) == (extract3.length-1)) {
                                    isLength = true;
                                    stat = 1;
                                    break;
                                } else {
                                    i++;
                                }
                            } else {
                                i++;
                            }
                            setBit(extract3,i,getBit(embedByte,x*8+6));
                            if ((i+1) % 8 == 0) {
                                if ((i/8) == (extract3.length-1)) {
                                    isLength = true;
                                    stat = 2;
                                    break;
                                } else {
                                    i++;
                                }
                            } else {
                                i++;
                            }
                            setBit(extract3,i,getBit(embedByte,x*8+7));
                            if ((i+1) % 8 == 0) {
                                if ((i/8) == (extract3.length-1)) {
                                    isLength = true;
                                    stat = 3;
                                    break;
                                } else {
                                    i++;
                                    x+=rand.nextInt(5) + 1;
                                }
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        }

                        System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    } else {
                        isError = true;
                        extractByte = new byte[100];

                        byte[] extract3 = new byte[100];
                        i = 0;
                        x+=rand.nextInt(5) + 1;
                        isLength = false;
                        while (!isLength && x < (int)embedByte.length) { 
                            setBit(extract3,i,getBit(embedByte,x*8+7));
                            if ((i+1) % 8 == 0) {
                                if ((i/8) == (extract3.length-1)) {
                                    isLength = true;
                                } else {
                                    i++;
                                    x+=rand.nextInt(5) + 1;
                                }
                            } else {
                                i++;
                                x+=rand.nextInt(5) + 1;
                            }
                        }
                        System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
                    }
                }
            } else {
                isError = true;
                extractByte = new byte[100];

                byte[] extract3 = new byte[100];
                i = 0;
                x+=rand.nextInt(5) + 1;
                isLength = false;
                while (!isLength && x < (int)embedByte.length) { 
                    setBit(extract3,i,getBit(embedByte,x*8+7));
                    if ((i+1) % 8 == 0) {
                        if ((i/8) == (extract3.length-1)) {
                            isLength = true;
                        } else {
                            i++;
                            x+=rand.nextInt(5) + 1;
                        }
                    } else {
                        i++;
                        x+=rand.nextInt(5) + 1;
                    }
                }
                System.arraycopy(extract3, 0, extractByte, 0, extractByte.length);
            }
        }
    }
    
    public double countPSNR() {
        float mse = 0;
        float counts = 0;
        int temp = 0;
        
        for (int i = 0; i < sourceByte.length; i++) {
            temp = (int) sourceByte[i] - (int)embedByte[i];
            counts = counts + temp * temp;
        }
            
        mse = (float) counts / (float) sourceByte.length;
            
        double psnr = 10 * Math.log10((double)(255 * 255) / (double) mse);
        return psnr;
    }
    
    private static int getBit(byte[] data, int pos) {
        int posByte = pos/8; 
        int posBit = pos%8;
        byte valByte = data[posByte];
        int valInt = valByte>>(8-(posBit+1)) & 0x0001;
        return valInt;
    }
    
    private static void setBit(byte[] data, int pos, int val) {
        int posByte = pos/8; 
        int posBit = pos%8;
        byte oldByte = data[posByte];
        oldByte = (byte) (((0xFF7F>>posBit) & oldByte) & 0x00FF);
        byte newByte = (byte) ((val<<(8-(posBit+1))) | oldByte);
        data[posByte] = newByte;
    }
    
}
